using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

using DirkRettschlag.Utils;
using System.Threading;
using System.Diagnostics;

namespace Departure
{
    public partial class ctrlStation : UserControl
    {
        #region Delegates
        
        private delegate void RequestDelegate(string Source, bool Error);
        private delegate void BuildDataDelegate(string Time, string Train, string Direction, string Platform, string Later, string FullDateTime, string Error, bool isError, bool done, bool update, int currentitem, int allitems);
        public delegate void SetRefreshButtonEventDelegate(string internalName, bool enabled);
        public delegate void SetCountdownEventDelegate(string countdownTime, string train, string later);

        #endregion Delegates

        #region Events

        public event SetRefreshButtonEventDelegate OnSetRefreshButton;
        public event SetCountdownEventDelegate OnSetCountdown;

        #endregion Events

        #region Variables

        StationSettings stationSettings;
        GeneralSettings generalSettings;
        bool isUpdating;

        #endregion Variables

        #region Properties

        public StationSettings StationSettings
        {
            get { return this.stationSettings; }
            set { this.stationSettings = value; }
        }

        public GeneralSettings GeneralSettings
        {
            set { this.generalSettings = value; }
        }

        public bool IsUpdating
        {
            get { return this.isUpdating; }
        }

        #endregion Properties

        #region Constructor
        public ctrlStation(string internalName, GeneralSettings generalSettings)
        {
            InitializeComponent();

            ResizeColumns(this.lsvMainStation);

            stationSettings = new StationSettings(internalName);

            stationSettings.getSettings();

            this.generalSettings = generalSettings;
        }
        #endregion Constructor

        #region Public Methods

        public void RefreshDepartures()
        {
            if (Utilities.Connected() || generalSettings.AutoConnect)
            {
                Cursor.Current = Cursors.WaitCursor;

                if (OnSetRefreshButton != null)
                    OnSetRefreshButton(this.Name, false);
                
                labelProgressStation.Text = "Retrieving Data...";
                labelProgressStation.Visible = true;
                lock (lsvMainStation)
                    lsvMainStation.Items.Clear();
                isUpdating = true;

                GetData();
            }
        }

        public void RemovePastDepartures()
        {
            try
            {
                // Hack for ListViews without Items
                if (lsvMainStation.Items.Count > 0)
                {
                }
            }
            catch
            {
                return;
            }

            if (lsvMainStation.Items.Count > 0)
            {
                for (int i = lsvMainStation.Items.Count - 1; i >= 0; i--)
                {
                    double correction = 0;
                    if (lsvMainStation.Items[i].SubItems[4].Text != "" && lsvMainStation.Items[i].SubItems[4].Text.IndexOf("approx. ") >= 0)
                        correction = double.Parse(lsvMainStation.Items[i].SubItems[4].Text.Replace("approx. ", "").Replace(" minutes later", ""));

                    DateTime corrected = DateTime.FromFileTimeUtc(long.Parse(lsvMainStation.Items[i].SubItems[5].Text)).AddMinutes(correction);
                    if (corrected < DateTime.Now)
                    {
                        Invoking.RemoveItem(lsvMainStation, i);
                    }
                }
            }

        }

        public void FocusListView()
        {
            lsvMainStation.Focus();
        }

        public void SaveDepartures()
        {
            DataTable dt = new DataTable("Departure");
            try
            {
                for (int i = 0; i < lsvMainStation.Columns.Count; i++) 
                {
                    dt.Columns.Add(Invoking.GetColumnHeaderText(lsvMainStation, i).Replace(" ","_"), typeof(string));
                }
                object[] vals = new object[lsvMainStation.Columns.Count];
                foreach (ListViewItem item in lsvMainStation.Items)
                {
                    ListViewItem.ListViewSubItemCollection items = item.SubItems;
                    for (int i = 0; i < vals.Length; i++)
                    {
                        vals[i] = items[i].Text;
                    }
                    dt.Rows.Add(vals);
                }
                dt.WriteXml(Utilities.AppPath() + "\\" + this.Name + ".xml");
            }
            catch
            {
            }

        }

        public void LoadDepartures()
        {
            DataTable dt = new DataTable("Departure");
            try
            {
                if (System.IO.File.Exists(Utilities.AppPath() + "\\" + this.Name + ".xml"))
                {
                    dt.ReadXmlSchema(Utilities.AppPath() + "\\StationSchema.xml");
                    dt.ReadXml(Utilities.AppPath() + "\\" + this.Name + ".xml");

                    foreach (DataRow dr in dt.Rows)
                    {
                        ListViewItem lvi;

                        lvi = new ListViewItem(dr["Time"].ToString());

                        lvi.SubItems.Add(dr["Train"].ToString());
                        lvi.SubItems.Add(dr["Direction"].ToString());
                        lvi.SubItems.Add(dr["Platform"].ToString());
                        lvi.SubItems.Add(dr["Later"].ToString());
                        lvi.SubItems.Add(dr["Full_DateTime"].ToString());

                        if (dr["Later"].ToString() != "")
                        {
                            lvi.ForeColor = Color.Red;
                        }

                        Invoking.AddListViewItem(lsvMainStation, lvi);
                    }
                   
                }

            }
            catch (Exception ex)
            {
            }

        }


        #endregion Public Methods

        #region Private Methods

        private void GetData()
        {
            string URL = "";

            if (generalSettings.UseWAP)
            {
                URL = "http://wap.bahn.de/bin/mobil/bhftafel.exe/eow?si=" + stationSettings.Station + "&ti=actual&bt=dep&p=" + stationSettings.Transfers + "&max=50&tn=&tns=1&start=yes";
            }
            else
            {
                URL = "http://reiseauskunft.bahn.de/bin/bhftafel.exe/en?L=ua_pda&input=" + stationSettings.Station + "&time=actual&boardType=dep&productsFilter=" + stationSettings.Transfers + "&start=Anzeigen&distance=1";
            }

            RequestDelegate requestDone = new RequestDelegate(RequestCallback);

            RequestThread wt = new RequestThread(this, requestDone, URL, generalSettings.UserAgent, generalSettings.HTTPHeader);
            Thread t = new Thread(new ThreadStart(wt.RunProcess));
            t.IsBackground = true; //make them a daemon - prevent thread callback issues
            t.Start();

        }

        private void RequestCallback(string Source, bool Error)
        {

            if (Error == false)
            {
                BuildData(Source);

            }
            else
            {
                labelProgressStation.Text = "";
                labelProgressStation.Visible = false;
                isUpdating = false;

                Cursor.Current = Cursors.Default;
                MessageBox.Show(Source, "An error occured");
            }
        }

        private void BuildData(string source)
        {
           
            labelProgressStation.Text = "Filtering Data...";
            lsvMainStation.BeginUpdate();

            BuildDataDelegate buildDataDone = new BuildDataDelegate(BuildDataCallback);

            BuildDataThread wt = new BuildDataThread(this, buildDataDone, source, stationSettings, generalSettings);
            Thread t = new Thread(new ThreadStart(wt.RunProcess));
            t.IsBackground = true; //make them a daemon - prevent thread callback issues
            t.Start();

        }

        private void BuildDataCallback(string Time, string Train, string Direction, string Platform, string Later, string FullDateTime, string Error, bool isError, bool done, bool update, int currentitem, int allitems)
        {
            if (isError)
            {
                labelProgressStation.Text = "";
                labelProgressStation.Visible = false;
                isUpdating = false;
                lsvMainStation.EndUpdate();

                Cursor.Current = Cursors.Default;
                MessageBox.Show(Error, "An error occured");
            }
            else if (done)
            {
                // TODO
                //if (!backgroundWorkerLoadSave.IsBusy)
                //    backgroundWorkerLoadSave.RunWorkerAsync(new object[] { "Save", StationIndex });

               
                labelProgressStation.Text = "";
                labelProgressStation.Visible = false;
                ResizeColumns(lsvMainStation);
                isUpdating = false;
                lsvMainStation.EndUpdate();

                Cursor.Current = Cursors.Default;

                if (OnSetRefreshButton != null)
                    OnSetRefreshButton(this.Name, true);

            }
            else if (update)
            {
                lock (labelProgressStation)
                {
                    labelProgressStation.Text = string.Format("Filtering Trains ({0}/{1})", currentitem, allitems);
                    labelProgressStation.Refresh();
                    //Debug.WriteLine(labelProgressStation.Text);
                }
            }
            else
            {
                ListViewItem lvi;

                lvi = new ListViewItem(Time);

                lvi.SubItems.Add(Train);
                lvi.SubItems.Add(Direction);
                lvi.SubItems.Add(Platform);
                lvi.SubItems.Add(Later);
                lvi.SubItems.Add(FullDateTime);

                if (Later != "")
                {
                    lvi.ForeColor = Color.Red;
                }

                lock (lsvMainStation)
                    lsvMainStation.Items.Add(lvi);

            }

        }

        private void ResizeColumns(ListView listview)
        {
            for (int i = 0; i < listview.Columns.Count - 1; i++)
            {
                listview.Columns[i].Width = -2;
            }

            listview.Columns[listview.Columns.Count - 1].Width = 0;
        }

        private void mniCountdown_Click(object sender, EventArgs e)
        {
            string countdownTime = "";
            string train = "";
            string later = "";

            if (lsvMainStation.SelectedIndices.Count > 0)
            {
                countdownTime = lsvMainStation.Items[lsvMainStation.SelectedIndices[0]].SubItems[5].Text;
                train = generalSettings.CountdownTrainFormat.Replace("%TI%", lsvMainStation.Items[lsvMainStation.SelectedIndices[0]].SubItems[0].Text);
                train = train.Replace("%TR%", lsvMainStation.Items[lsvMainStation.SelectedIndices[0]].SubItems[1].Text);
                train = train.Replace("%DI%", lsvMainStation.Items[lsvMainStation.SelectedIndices[0]].SubItems[2].Text);
                train = train.Replace("%PL%", lsvMainStation.Items[lsvMainStation.SelectedIndices[0]].SubItems[3].Text);
                later = lsvMainStation.Items[lsvMainStation.SelectedIndices[0]].SubItems[4].Text;
            }

            if (OnSetCountdown != null)
                OnSetCountdown(countdownTime, train, later);

        }

        #endregion Private Methods
    }
}
